bitkeeper revision 1.825.3.13 (4067341aEVBylJ8rvZlNJ-_l5YeAoQ)
authorkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Sun, 28 Mar 2004 20:22:50 +0000 (20:22 +0000)
committerkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Sun, 28 Mar 2004 20:22:50 +0000 (20:22 +0000)
mkbuildtree, pci-pc.c, Makefile, defconfig-physdev, physdev.h, physdev.c:
  PCI-access updates for new IO world.
.del-pci-irq.c~626134b3f85d1f48:
  Delete: xenolinux-2.4.25-sparse/arch/xen/kernel/pci-irq.c
.del-pci-i386.h~17514121c175844:
  Delete: xenolinux-2.4.25-sparse/arch/xen/kernel/pci-i386.h
.del-pci-i386.c~d13b1a4728189770:
  Delete: xenolinux-2.4.25-sparse/arch/xen/kernel/pci-i386.c

.rootkeys
xen/common/physdev.c
xen/include/hypervisor-ifs/physdev.h
xenolinux-2.4.25-sparse/arch/xen/defconfig-physdev
xenolinux-2.4.25-sparse/arch/xen/kernel/Makefile
xenolinux-2.4.25-sparse/arch/xen/kernel/pci-i386.c [deleted file]
xenolinux-2.4.25-sparse/arch/xen/kernel/pci-i386.h [deleted file]
xenolinux-2.4.25-sparse/arch/xen/kernel/pci-irq.c [deleted file]
xenolinux-2.4.25-sparse/arch/xen/kernel/pci-pc.c
xenolinux-2.4.25-sparse/mkbuildtree

index ee5806cabe1f8f4774bf98505d7c413103e63355..7a74d6af0b62e2fabcb62cbfb25122bde5e59e4b 100644 (file)
--- a/.rootkeys
+++ b/.rootkeys
 3e5a4e653U6cELGv528IxOLHvCq8iA xenolinux-2.4.25-sparse/arch/xen/kernel/irq.c
 3e5a4e65muT6SU3ck47IP87Q7Ti5hA xenolinux-2.4.25-sparse/arch/xen/kernel/ldt.c
 4051db84bZeRX7a_Kh6VyyDuT5FOIg xenolinux-2.4.25-sparse/arch/xen/kernel/pci-dma.c
-4051db89iiHs38tWGkoW_RukNyaBHw xenolinux-2.4.25-sparse/arch/xen/kernel/pci-i386.c
-4051db8dJYX86ZCLA-WfTW2dAyrehw xenolinux-2.4.25-sparse/arch/xen/kernel/pci-i386.h
-4051db91BenvDZEMZxQCGkQyJYoG5w xenolinux-2.4.25-sparse/arch/xen/kernel/pci-irq.c
 4051db95N9N99FjsRwi49YKUNHWI8A xenolinux-2.4.25-sparse/arch/xen/kernel/pci-pc.c
 3e5a4e65IGt3WwQDNiL4h-gYWgNTWQ xenolinux-2.4.25-sparse/arch/xen/kernel/process.c
 3e5a4e66tR-qJMLj3MppcKqmvuI2XQ xenolinux-2.4.25-sparse/arch/xen/kernel/setup.c
index 11746785f3ee7af28434bba96d597af94f897279..a3f3fb7f52c00a5d588aae3a9d141714a3a9ed73 100644 (file)
@@ -1,11 +1,8 @@
 /* -*-  Mode:C; c-basic-offset:4; tab-width:4 -*-
  ****************************************************************************
- * (C) 2004 - Rolf Neugebauer - Intel Research Cambridge
+ * (c) 2004 - Rolf Neugebauer - Intel Research Cambridge
+ * (c) 2004 - Keir Fraser - University of Cambridge
  ****************************************************************************
- *
- *        File: phys_dev.c
- *      Author: Rolf Neugebauer (rolf.neugebauer@intel.com)
- *        Date: Feb 2004
  * 
  * Description: allows a domain to access devices on the PCI bus
  *
@@ -47,6 +44,9 @@
 #include <hypervisor-ifs/hypervisor-if.h>
 #include <hypervisor-ifs/physdev.h>
 
+/* Called by PHYSDEV_PCI_INITIALISE_DEVICE to finalise IRQ routing. */
+extern void pcibios_enable_irq(struct pci_dev *dev);
+
 #if 1
 #define DBG(_x...)
 #else
@@ -267,7 +267,7 @@ inline static int check_dev_acc (struct task_struct *p,
  * error is flagged.
  */
 static int do_base_address_access(phys_dev_t *pdev, int acc,
-                                  int seg, int bus, int dev, int func, 
+                                  int bus, int dev, int func, 
                                   int reg, int len, u32 *val)
 {
     int idx, st_bit, ret = -EINVAL;
@@ -293,7 +293,7 @@ static int do_base_address_access(phys_dev_t *pdev, int acc,
             clear_bit(st_bit, &pdev->state);
 
             /* check if guest tries to restore orig value */
-            ret = pci_config_read(seg, bus, dev, func, reg, len, &orig_val);
+            ret = pci_config_read(0, bus, dev, func, reg, len, &orig_val);
             if ( *val != orig_val ) 
             {
                 printk("caution: guest tried to change base address range.\n");
@@ -311,12 +311,12 @@ static int do_base_address_access(phys_dev_t *pdev, int acc,
         if ( !test_bit(st_bit, &pdev->state) )
         {
             /* just read and return */
-            ret = pci_config_read(seg, bus, dev, func, reg, len, val);
+            ret = pci_config_read(0, bus, dev, func, reg, len, val);
         }
         else
         {
             /* fake value */
-            ret = pci_config_read(seg, bus, dev, func, reg, len, &orig_val);
+            ret = pci_config_read(0, bus, dev, func, reg, len, &orig_val);
 
             sz  = res->end - res->start;
 
@@ -358,8 +358,8 @@ static int do_base_address_access(phys_dev_t *pdev, int acc,
  * pretty much the same as a above
  */
 static int do_rom_address_access(phys_dev_t *pdev, int acc,
-                                  int seg, int bus, int dev, int func, 
-                                  int reg, int len, u32 *val)
+                                 int bus, int dev, int func, 
+                                 int reg, int len, u32 *val)
 {
     int st_bit, ret = -EINVAL;
     u32 orig_val, sz;
@@ -383,7 +383,7 @@ static int do_rom_address_access(phys_dev_t *pdev, int acc,
             clear_bit(st_bit, &pdev->state);
             
             /* check if guest tries to restore orig value */
-            ret = pci_config_read(seg, bus, dev, func, reg, len, &orig_val);
+            ret = pci_config_read(0, bus, dev, func, reg, len, &orig_val);
             if ( (*val != orig_val) ) 
             {
                 if (*val != 0x00000000 )
@@ -409,12 +409,12 @@ static int do_rom_address_access(phys_dev_t *pdev, int acc,
        if ( !test_bit(st_bit, &pdev->state) )
         {
             /* just read and return */
-            ret = pci_config_read(seg, bus, dev, func, reg, len, val);
+            ret = pci_config_read(0, bus, dev, func, reg, len, val);
         }
         else
         {
             /* fake value */
-            ret = pci_config_read(seg, bus, dev, func, reg, len, &orig_val);
+            ret = pci_config_read(0, bus, dev, func, reg, len, &orig_val);
             sz  = res->end - res->start;
             *val = 0xffffffff;
             /* leave bit 0 untouched */
@@ -438,18 +438,17 @@ static int do_rom_address_access(phys_dev_t *pdev, int acc,
  * For some registers for read-only devices (e.g. address base registers)
  * we need to maintain a state machine.
  */
-static long pci_cfgreg_read(int seg, int bus, int dev, int func, int reg,
+static long pci_cfgreg_read(int bus, int dev, int func, int reg,
                             int len, u32 *val)
 {
-    int ret = 0;
+    int ret;
     phys_dev_t *pdev;
 
-    ret = check_dev_acc(current, bus, dev, func, &pdev);
-    if ( ret != 0 )
+    if ( (ret = check_dev_acc(current, bus, dev, func, &pdev)) != 0 )
         return ret;
 
-    /* fake out read requests for some registers */
-    switch (reg)
+    /* Fake out read requests for some registers. */
+    switch ( reg )
     {
     case PCI_BASE_ADDRESS_0:
     case PCI_BASE_ADDRESS_1:
@@ -457,23 +456,26 @@ static long pci_cfgreg_read(int seg, int bus, int dev, int func, int reg,
     case PCI_BASE_ADDRESS_3:
     case PCI_BASE_ADDRESS_4:
     case PCI_BASE_ADDRESS_5:
-        ret = do_base_address_access (pdev, ACC_READ, seg, bus, dev, 
-                                      func, reg, len, val);
-        return ret;
+        ret = do_base_address_access(pdev, ACC_READ, bus, dev, 
+                                     func, reg, len, val);
         break;
+
     case PCI_ROM_ADDRESS:
-        ret = do_rom_address_access (pdev, ACC_READ, seg, bus, dev, 
-                                      func, reg, len, val);
-        return ret;
+        ret = do_rom_address_access(pdev, ACC_READ, bus, dev, 
+                                    func, reg, len, val);
         break;        
+
+    case PCI_INTERRUPT_LINE:
+        ret = pdev->dev->irq;
+        break;
+
     default:
+        ret = pci_config_read(0, bus, dev, func, reg, len, val);        
+        DBG("pci read : %02x:%02x:%02x reg=0x%02x len=0x%02x val=0x%08x\n",
+            bus, dev, func, reg, len, *val);
         break;
     }
 
-    ret = pci_config_read(seg, bus, dev, func, reg, len, val);
-
-    DBG("pci read : %02x:%02x:%02x reg=0x%02x len=0x%02x val=0x%08x\n",
-        bus, dev, func, reg, len, *val);
     return ret;
 }
 
@@ -483,14 +485,13 @@ static long pci_cfgreg_read(int seg, int bus, int dev, int func, int reg,
  * for some registers a state machine is maintained to fake out r/w access.
  * By default no write access is allowed but we may change that in the future.
  */
-static long pci_cfgreg_write(int seg, int bus, int dev, int func, int reg,
+static long pci_cfgreg_write(int bus, int dev, int func, int reg,
                              int len, u32 val)
 {
-    int ret = 0;
+    int ret;
     phys_dev_t *pdev;
 
-    ret = check_dev_acc(current, bus, dev, func, &pdev);
-    if ( ret != 0 )
+    if ( (ret = check_dev_acc(current, bus, dev, func, &pdev)) != 0 )
         return ret;
 
     /* special treatment for some registers */
@@ -502,73 +503,61 @@ static long pci_cfgreg_write(int seg, int bus, int dev, int func, int reg,
     case PCI_BASE_ADDRESS_3:
     case PCI_BASE_ADDRESS_4:
     case PCI_BASE_ADDRESS_5:
-        ret = do_base_address_access (pdev, ACC_WRITE, seg, bus, dev, 
+        ret = do_base_address_access (pdev, ACC_WRITE, bus, dev, 
                                       func, reg, len, &val);
         return ret;
         break;
+
     case PCI_ROM_ADDRESS:
-        ret = do_rom_address_access (pdev, ACC_WRITE, seg, bus, dev, 
+        ret = do_rom_address_access (pdev, ACC_WRITE, bus, dev, 
                                       func, reg, len, &val);
         return ret;
         break;        
-#if 0
-    case 0xe0: /* XXX some device drivers seem to write to this.... */
-        printk("pci write hack allowed %02x:%02x:%02x: "
-                   "reg=0x%02x len=0x%02x val=0x%08x\n",
-                   bus, dev, func, reg, len, val);
-        break;        
-#endif
+
     default:
-        //if ( pdev->flags != ACC_WRITE ) 
-        /* XXX for debug we disallow all write access */
+        if ( pdev->flags != ACC_WRITE ) 
         {
             printk("pci write not allowed %02x:%02x:%02x: "
                    "reg=0x%02x len=0x%02x val=0x%08x\n",
                    bus, dev, func, reg, len, val);
-            return -EPERM;
+            ret = -EPERM;
+        }
+        else
+        {
+            ret = pci_config_write(0, bus, dev, func, reg, len, val);
+            DBG("pci write: %02x:%02x:%02x reg=0x%02x len=0x%02x val=0x%08x\n",
+                bus, dev, func, reg, len, val);
         }
         break;
     }
 
-    ret = pci_config_write(seg, bus, dev, func, reg, len, val);
-
-    DBG("pci write: %02x:%02x:%02x reg=0x%02x len=0x%02x val=0x%08x\n",
-        bus, dev, func, reg, len, val);
     return ret;
 }
 
-/*
- * 
- * Interrupt handling
- * 
- */
-
 
-/*
- * return the IRQ xen assigned to the device.
- * This may be different to what is in the PCI confic space!
- * XXX RN: I'm not sure we need this. we could just intercept PCI config
- * reads on PCI_INTERRUPT_LINE and return the correct value.
- */
-static long pci_find_irq(int seg, int bus, int dev, int func, u32 *val)
+static long pci_probe_root_buses(u32 *busmask)
 {
-    int ret = 0;
     phys_dev_t *pdev;
+    struct list_head *tmp;
 
-    ret = check_dev_acc(current, bus, dev, func, &pdev);
-    if ( ret != 0 )
-        return ret;
+    memset(busmask, 0, 256/8);
+
+    list_for_each ( tmp, &current->pcidev_list )
+    {
+        pdev = list_entry(tmp, phys_dev_t, node);
+        set_bit(pdev->dev->bus->number, busmask);
+    }
 
-    *val = pdev->dev->irq;
     return 0;
 }
 
 
 /*
- * demux hypervisor call.
+ * Demuxing hypercall.
  */
 long do_physdev_op(physdev_op_t *uop)
 {
+    phys_dev_t *pdev;
     physdev_op_t op;
     long ret;
 
@@ -577,24 +566,35 @@ long do_physdev_op(physdev_op_t *uop)
 
     switch ( op.cmd )
     {
-    case PHYSDEVOP_CFGREG_READ:
-        ret = pci_cfgreg_read(op.u.cfg_read.seg, op.u.cfg_read.bus,
-                              op.u.cfg_read.dev, op.u.cfg_read.func,
-                              op.u.cfg_read.reg, op.u.cfg_read.len,
-                              &op.u.cfg_read.value);
+    case PHYSDEVOP_PCI_CFGREG_READ:
+        ret = pci_cfgreg_read(op.u.pci_cfgreg_read.bus,
+                              op.u.pci_cfgreg_read.dev, 
+                              op.u.pci_cfgreg_read.func,
+                              op.u.pci_cfgreg_read.reg, 
+                              op.u.pci_cfgreg_read.len,
+                              &op.u.pci_cfgreg_read.value);
         break;
 
-    case PHYSDEVOP_CFGREG_WRITE:
-        ret = pci_cfgreg_write(op.u.cfg_write.seg, op.u.cfg_write.bus,
-                               op.u.cfg_write.dev, op.u.cfg_write.func,
-                               op.u.cfg_write.reg, op.u.cfg_write.len,
-                               op.u.cfg_write.value);
+    case PHYSDEVOP_PCI_CFGREG_WRITE:
+        ret = pci_cfgreg_write(op.u.pci_cfgreg_write.bus,
+                               op.u.pci_cfgreg_write.dev, 
+                               op.u.pci_cfgreg_write.func,
+                               op.u.pci_cfgreg_write.reg, 
+                               op.u.pci_cfgreg_write.len,
+                               op.u.pci_cfgreg_write.value);
         break;
 
-    case PHYSDEVOP_FIND_IRQ:
-        ret = pci_find_irq(op.u.find_irq.seg, op.u.find_irq.bus,
-                           op.u.find_irq.dev, op.u.find_irq.func,
-                           &op.u.find_irq.irq);
+    case PHYSDEVOP_PCI_INITIALISE_DEVICE:
+        if ( (ret = check_dev_acc(current, 
+                                  op.u.pci_initialise_device.bus, 
+                                  op.u.pci_initialise_device.dev, 
+                                  op.u.pci_initialise_device.func, 
+                                  &pdev)) == 0 )
+            pcibios_enable_irq(pdev->dev);
+        break;
+
+    case PHYSDEVOP_PCI_PROBE_ROOT_BUSES:
+        ret = pci_probe_root_buses(op.u.pci_probe_root_buses.busmask);
         break;
 
     case PHYSDEVOP_UNMASK_IRQ:
@@ -611,10 +611,7 @@ long do_physdev_op(physdev_op_t *uop)
 }
 
 
-/*
- * Domain 0 has read access to all devices.
- * XXX this is a bit of a hack
- */
+/* Domain 0 has read access to all devices. */
 void physdev_init_dom0(struct task_struct *p)
 {
     struct pci_dev *dev;
@@ -627,7 +624,7 @@ void physdev_init_dom0(struct task_struct *p)
         /* add device */
         pdev = kmalloc(sizeof(phys_dev_t), GFP_KERNEL);
         pdev->dev = dev;
-        pdev->flags = ACC_READ;
+        pdev->flags = ACC_WRITE;
         pdev->state = 0;
         pdev->owner = p;
         list_add(&pdev->node, &p->pcidev_list);
index 383bb13097bcb792702e068521e651cc8bde9435..914a555981c5f46469780a2a16b99b72dc15f6d1 100644 (file)
@@ -1,70 +1,66 @@
 /* -*-  Mode:C; c-basic-offset:4; tab-width:4 -*-
  ****************************************************************************
- * (C) 2004 - Rolf Neugebauer - Intel Research Cambridge
+ * (c) 2004 - Rolf Neugebauer - Intel Research Cambridge
+ * (c) 2004 - Keir Fraser - University of Cambridge
  ****************************************************************************
- *
- *        File: physdev.h
- *      Author: Rolf Neugebauer (neugebar@dcs.gla.ac.uk)
- *        Date: Feb 2004
- * 
  * Description: Interface for domains to access physical devices on the PCI bus
  */
 
 #ifndef __HYPERVISOR_IFS_PHYSDEV_H__
 #define __HYPERVISOR_IFS_PHYSDEV_H__
 
-/*
- * Commands to HYPERVISOR_physdev_op()
- */
-#define PHYSDEVOP_CFGREG_READ   0
-#define PHYSDEVOP_CFGREG_WRITE  1
-#define PHYSDEVOP_FIND_IRQ      2
-#define PHYSDEVOP_UNMASK_IRQ    3
+/* Commands to HYPERVISOR_physdev_op() */
+#define PHYSDEVOP_PCI_CFGREG_READ       0
+#define PHYSDEVOP_PCI_CFGREG_WRITE      1
+#define PHYSDEVOP_PCI_INITIALISE_DEVICE 2
+#define PHYSDEVOP_PCI_PROBE_ROOT_BUSES  3
+#define PHYSDEVOP_UNMASK_IRQ            4
 
-/* read pci config */
-typedef struct physdevop_cfgreg_read_st
+/* Read from PCI configuration space. */
+typedef struct physdevop_pci_cfgreg_read_st
 {
-    int seg;        /* IN */
     int bus;        /* IN */
     int dev;        /* IN */
     int func;       /* IN */
     int reg;        /* IN */
     int len;        /* IN */
     u32 value;      /* OUT */
-} physdevop_cfgreg_read_t;
+} physdevop_pci_cfgreg_read_t;
 
-/* write pci config */
-typedef struct physdevop_cfgred_write_st
+/* Write to PCI configuration space. */
+typedef struct physdevop_pci_cfgreg_write_st
 {
-    int seg;        /* IN */
     int bus;        /* IN */
     int dev;        /* IN */
     int func;       /* IN */
     int reg;        /* IN */
     int len;        /* IN */
     u32 value;      /* IN */
-} physdevop_cfgreg_write_t;
+} physdevop_pci_cfgreg_write_t;
 
-/* get the real IRQ for a device */
-typedef struct physdevop_find_irq_st
+/* Do final initialisation of a PCI device (e.g., last-moment IRQ routing). */
+typedef struct physdevop_pci_initialise_device_st
 {
-    int seg;      /* IN */
     int bus;      /* IN */
     int dev;      /* IN */
     int func;     /* IN */
-    u32 irq;      /* OUT */
-} physdevop_find_irq_t;
+} physdevop_pci_initialise_device_t;
+
+/* Find the root buses for subsequent scanning. */
+typedef struct physdevop_pci_probe_root_buses_st
+{
+    u32 busmask[256/32]; /* OUT */
+} physdevop_pci_probe_root_buses_t;
 
 typedef struct _physdev_op_st 
 {
     unsigned long cmd;
-
-    /* command parameters */
     union
     {
-        physdevop_cfgreg_read_t  cfg_read;
-        physdevop_cfgreg_write_t cfg_write;
-        physdevop_find_irq_t     find_irq;
+        physdevop_pci_cfgreg_read_t       pci_cfgreg_read;
+        physdevop_pci_cfgreg_write_t      pci_cfgreg_write;
+        physdevop_pci_initialise_device_t pci_initialise_device;
+        physdevop_pci_probe_root_buses_t  pci_probe_root_buses;
     } u;
 } physdev_op_t;
 
index 52922f5bf1e3ad383d81a8ca48d9cca4d0ede5ff..e6a213757ca93383b3f3d3560c07b7fb8399bfb4 100644 (file)
@@ -370,9 +370,9 @@ CONFIG_CHR_DEV_SG=y
 # CONFIG_BLK_DEV_3W_XXXX_RAID is not set
 # CONFIG_SCSI_7000FASST is not set
 # CONFIG_SCSI_ACARD is not set
-CONFIG_SCSI_AHA152X=y
-CONFIG_SCSI_AHA1542=y
-CONFIG_SCSI_AHA1740=y
+# CONFIG_SCSI_AHA152X is not set
+# CONFIG_SCSI_AHA1542 is not set
+# CONFIG_SCSI_AHA1740 is not set
 CONFIG_SCSI_AACRAID=y
 # CONFIG_SCSI_AIC7XXX is not set
 CONFIG_SCSI_AIC79XX=y
@@ -400,9 +400,9 @@ CONFIG_SCSI_DTC3280=y
 # CONFIG_SCSI_EATA_PIO is not set
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
 # CONFIG_SCSI_GDTH is not set
-CONFIG_SCSI_GENERIC_NCR5380=y
+# CONFIG_SCSI_GENERIC_NCR5380 is not set
 # CONFIG_SCSI_GENERIC_NCR53C400 is not set
-CONFIG_SCSI_G_NCR5380_PORT=y
+# CONFIG_SCSI_G_NCR5380_PORT is not set
 # CONFIG_SCSI_G_NCR5380_MEM is not set
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
index 5abf0a0d6244ab0c6fec9cba096ce55ac6c64bfd..78f5314004616640707f809117f18ddbda04e08c 100644 (file)
@@ -13,7 +13,7 @@ obj-y := process.o semaphore.o signal.o entry.o traps.o irq.o  \
                i386_ksyms.o i387.o evtchn.o pci-dma.o
 
 ifdef CONFIG_PCI
-obj-y  += pci-i386.o pci-pc.o pci-irq.o
+obj-y  += pci-i386.o pci-pc.o
 endif
 
 include $(TOPDIR)/Rules.make
diff --git a/xenolinux-2.4.25-sparse/arch/xen/kernel/pci-i386.c b/xenolinux-2.4.25-sparse/arch/xen/kernel/pci-i386.c
deleted file mode 100644 (file)
index 96dcdde..0000000
+++ /dev/null
@@ -1,410 +0,0 @@
-/*
- *     Low-Level PCI Access for i386 machines
- *
- * Copyright 1993, 1994 Drew Eckhardt
- *      Visionary Computing
- *      (Unix and Linux consulting and custom programming)
- *      Drew@Colorado.EDU
- *      +1 (303) 786-7975
- *
- * Drew's work was sponsored by:
- *     iX Multiuser Multitasking Magazine
- *     Hannover, Germany
- *     hm@ix.de
- *
- * Copyright 1997--2000 Martin Mares <mj@ucw.cz>
- *
- * For more information, please consult the following manuals (look at
- * http://www.pcisig.com/ for how to get them):
- *
- * PCI BIOS Specification
- * PCI Local Bus Specification
- * PCI to PCI Bridge Specification
- * PCI System Design Guide
- *
- *
- * CHANGELOG :
- * Jun 17, 1994 : Modified to accommodate the broken pre-PCI BIOS SPECIFICATION
- *     Revision 2.0 present on <thys@dennis.ee.up.ac.za>'s ASUS mainboard.
- *
- * Jan 5,  1995 : Modified to probe PCI hardware at boot time by Frederic
- *     Potter, potter@cao-vlsi.ibp.fr
- *
- * Jan 10, 1995 : Modified to store the information about configured pci
- *      devices into a list, which can be accessed via /proc/pci by
- *      Curtis Varner, cvarner@cs.ucr.edu
- *
- * Jan 12, 1995 : CPU-PCI bridge optimization support by Frederic Potter.
- *     Alpha version. Intel & UMC chipset support only.
- *
- * Apr 16, 1995 : Source merge with the DEC Alpha PCI support. Most of the code
- *     moved to drivers/pci/pci.c.
- *
- * Dec 7, 1996  : Added support for direct configuration access of boards
- *      with Intel compatible access schemes (tsbogend@alpha.franken.de)
- *
- * Feb 3, 1997  : Set internal functions to static, save/restore flags
- *     avoid dead locks reading broken PCI BIOS, werner@suse.de 
- *
- * Apr 26, 1997 : Fixed case when there is BIOS32, but not PCI BIOS
- *     (mj@atrey.karlin.mff.cuni.cz)
- *
- * May 7,  1997 : Added some missing cli()'s. [mj]
- * 
- * Jun 20, 1997 : Corrected problems in "conf1" type accesses.
- *      (paubert@iram.es)
- *
- * Aug 2,  1997 : Split to PCI BIOS handling and direct PCI access parts
- *     and cleaned it up...     Martin Mares <mj@atrey.karlin.mff.cuni.cz>
- *
- * Feb 6,  1998 : No longer using BIOS to find devices and device classes. [mj]
- *
- * May 1,  1998 : Support for peer host bridges. [mj]
- *
- * Jun 19, 1998 : Changed to use spinlocks, so that PCI configuration space
- *     can be accessed from interrupts even on SMP systems. [mj]
- *
- * August  1998 : Better support for peer host bridges and more paranoid
- *     checks for direct hardware access. Ugh, this file starts to look as
- *     a large gallery of common hardware bug workarounds (watch the comments)
- *     -- the PCI specs themselves are sane, but most implementors should be
- *     hit hard with \hammer scaled \magstep5. [mj]
- *
- * Jan 23, 1999 : More improvements to peer host bridge logic. i450NX fixup. [mj]
- *
- * Feb 8,  1999 : Added UM8886BF I/O address fixup. [mj]
- *
- * August  1999 : New resource management and configuration access stuff. [mj]
- *
- * Sep 19, 1999 : Use PCI IRQ routing tables for detection of peer host bridges.
- *               Based on ideas by Chris Frantz and David Hinds. [mj]
- *
- * Sep 28, 1999 : Handle unreported/unassigned IRQs. Thanks to Shuu Yamaguchi
- *               for a lot of patience during testing. [mj]
- *
- * Oct  8, 1999 : Split to pci-i386.c, pci-pc.c and pci-visws.c. [mj]
- */
-
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/errno.h>
-
-#include "pci-i386.h"
-
-void
-pcibios_update_resource(struct pci_dev *dev, struct resource *root,
-                       struct resource *res, int resource)
-{
-    u32 new, check;
-    int reg;
-
-    new = res->start | (res->flags & PCI_REGION_FLAG_MASK);
-    if (resource < 6) {
-        reg = PCI_BASE_ADDRESS_0 + 4*resource;
-    } else if (resource == PCI_ROM_RESOURCE) {
-        res->flags |= PCI_ROM_ADDRESS_ENABLE;
-        new |= PCI_ROM_ADDRESS_ENABLE;
-        reg = dev->rom_base_reg;
-    } else {
-        /* Somebody might have asked allocation of a non-standard resource */
-        return;
-    }
-       
-    pci_write_config_dword(dev, reg, new);
-    pci_read_config_dword(dev, reg, &check);
-    if ((new ^ check) & ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK)) {
-        printk(KERN_ERR "PCI: Error while updating region "
-               "%s/%d (%08x != %08x)\n", dev->slot_name, resource,
-               new, check);
-    }
-}
-
-/*
- * We need to avoid collisions with `mirrored' VGA ports
- * and other strange ISA hardware, so we always want the
- * addresses to be allocated in the 0x000-0x0ff region
- * modulo 0x400.
- *
- * Why? Because some silly external IO cards only decode
- * the low 10 bits of the IO address. The 0x00-0xff region
- * is reserved for motherboard devices that decode all 16
- * bits, so it's ok to allocate at, say, 0x2800-0x28ff,
- * but we want to try to avoid allocating at 0x2900-0x2bff
- * which might have be mirrored at 0x0100-0x03ff..
- */
-void
-pcibios_align_resource(void *data, struct resource *res,
-                      unsigned long size, unsigned long align)
-{
-    if (res->flags & IORESOURCE_IO) {
-        unsigned long start = res->start;
-
-        if (start & 0x300) {
-            start = (start + 0x3ff) & ~0x3ff;
-            res->start = start;
-        }
-    }
-}
-
-
-/*
- *  Handle resources of PCI devices.  If the world were perfect, we could
- *  just allocate all the resource regions and do nothing more.  It isn't.
- *  On the other hand, we cannot just re-allocate all devices, as it would
- *  require us to know lots of host bridge internals.  So we attempt to
- *  keep as much of the original configuration as possible, but tweak it
- *  when it's found to be wrong.
- *
- *  Known BIOS problems we have to work around:
- *     - I/O or memory regions not configured
- *     - regions configured, but not enabled in the command register
- *     - bogus I/O addresses above 64K used
- *     - expansion ROMs left enabled (this may sound harmless, but given
- *       the fact the PCI specs explicitly allow address decoders to be
- *       shared between expansion ROMs and other resource regions, it's
- *       at least dangerous)
- *
- *  Our solution:
- *     (1) Allocate resources for all buses behind PCI-to-PCI bridges.
- *         This gives us fixed barriers on where we can allocate.
- *     (2) Allocate resources for all enabled devices.  If there is
- *         a collision, just mark the resource as unallocated. Also
- *         disable expansion ROMs during this step.
- *     (3) Try to allocate resources for disabled devices.  If the
- *         resources were assigned correctly, everything goes well,
- *         if they weren't, they won't disturb allocation of other
- *         resources.
- *     (4) Assign new addresses to resources which were either
- *         not configured at all or misconfigured.  If explicitly
- *         requested by the user, configure expansion ROM address
- *         as well.
- */
-
-static void __init pcibios_allocate_bus_resources(struct list_head *bus_list)
-{
-    struct list_head *ln;
-    struct pci_bus *bus;
-    struct pci_dev *dev;
-    int idx;
-    struct resource *r, *pr;
-
-    /* Depth-First Search on bus tree */
-    for (ln=bus_list->next; ln != bus_list; ln=ln->next) {
-        bus = pci_bus_b(ln);
-        if ((dev = bus->self)) {
-            printk("alloc bus res: %s\n", dev->slot_name);
-            for (idx = PCI_BRIDGE_RESOURCES; idx < PCI_NUM_RESOURCES; idx++) {
-                r = &dev->resource[idx];
-                if (!r->start)
-                {
-                    printk("  res1: 0x%08lx-0x%08lx f=%lx\n",
-                           r->start, r->end, r->flags);
-
-                    continue;
-                }
-                pr = pci_find_parent_resource(dev, r);
-                if (!pr || request_resource(pr, r) < 0)
-                    printk(KERN_ERR "PCI: Cannot allocate resource region %d "
-                           "of bridge %s (%p)\n", idx, dev->slot_name, pr);
-                printk("  res2: %08lx-%08lx f=%lx\n",
-                       r->start, r->end, r->flags);
-            }
-        }
-        pcibios_allocate_bus_resources(&bus->children);
-    }
-}
-
-static void __init pcibios_allocate_resources(int pass)
-{
-    struct pci_dev *dev;
-    int idx, disabled;
-    u16 command;
-    struct resource *r, *pr;
-
-    pci_for_each_dev(dev) {
-        pci_read_config_word(dev, PCI_COMMAND, &command);
-        for(idx = 0; idx < 6; idx++) {
-            r = &dev->resource[idx];
-            if (r->parent)             /* Already allocated */
-                continue;
-            if (!r->start)             /* Address not assigned at all */
-                continue;
-            if (r->flags & IORESOURCE_IO)
-                disabled = !(command & PCI_COMMAND_IO);
-            else
-                disabled = !(command & PCI_COMMAND_MEMORY);
-            if (pass == disabled) {
-                printk("PCI: Resource %08lx-%08lx (f=%lx, d=%d, p=%d) (%s)\n",
-                       r->start, r->end, r->flags, disabled, pass, dev->slot_name);
-                pr = pci_find_parent_resource(dev, r);
-                if (!pr || request_resource(pr, r) < 0) {
-                    printk(KERN_ERR "PCI: Cannot allocate resource region %d"
-                           " of device %s (%p)\n", idx, dev->slot_name, pr);
-                    /* We'll assign a new address later */
-                    r->end -= r->start;
-                    r->start = 0;
-                }
-            }
-        }
-        if (!pass) {
-            r = &dev->resource[PCI_ROM_RESOURCE];
-            if (r->flags & PCI_ROM_ADDRESS_ENABLE) {
-                               /* Turn the ROM off, leave the resource region, but keep it unregistered. */
-                u32 reg;
-                printk("PCI: Switching off ROM of %s\n", dev->slot_name);
-                r->flags &= ~PCI_ROM_ADDRESS_ENABLE;
-                pci_read_config_dword(dev, dev->rom_base_reg, &reg);
-                pci_write_config_dword(dev, dev->rom_base_reg, reg & ~PCI_ROM_ADDRESS_ENABLE);
-            }
-        }
-    }
-}
-
-static void __init pcibios_assign_resources(void)
-{
-    struct pci_dev *dev;
-    int idx;
-    struct resource *r;
-
-    pci_for_each_dev(dev) {
-        int class = dev->class >> 8;
-
-        /* Don't touch classless devices and host bridges */
-        if (!class || class == PCI_CLASS_BRIDGE_HOST)
-            continue;
-
-        for(idx=0; idx<6; idx++) {
-            r = &dev->resource[idx];
-
-            /*
-             *  Don't touch IDE controllers and I/O ports of video cards!
-             */
-            if ((class == PCI_CLASS_STORAGE_IDE && idx < 4) ||
-                (class == PCI_CLASS_DISPLAY_VGA && (r->flags & IORESOURCE_IO)))
-                continue;
-
-            /*
-             *  We shall assign a new address to this resource, either because
-             *  the BIOS forgot to do so or because we have decided the old
-             *  address was unusable for some reason.
-             */
-            if (!r->start && r->end)
-                pci_assign_resource(dev, idx);
-        }
-
-        if (pci_probe & PCI_ASSIGN_ROMS) {
-            r = &dev->resource[PCI_ROM_RESOURCE];
-            r->end -= r->start;
-            r->start = 0;
-            if (r->end)
-                pci_assign_resource(dev, PCI_ROM_RESOURCE);
-        }
-    }
-}
-
-void __init pcibios_set_cacheline_size(void)
-{
-    struct cpuinfo_x86 *c = &boot_cpu_data;
-
-    pci_cache_line_size = 32 >> 2;
-    if (c->x86 >= 6 && c->x86_vendor == X86_VENDOR_AMD)
-        pci_cache_line_size = 64 >> 2; /* K7 & K8 */
-    else if (c->x86 > 6 && c->x86_vendor == X86_VENDOR_INTEL)
-        pci_cache_line_size = 128 >> 2;        /* P4 */
-}
-
-void __init pcibios_resource_survey(void)
-{
-    DBG("PCI: Allocating resources\n");
-    pcibios_allocate_bus_resources(&pci_root_buses);
-    pcibios_allocate_resources(0);
-    pcibios_allocate_resources(1);
-    pcibios_assign_resources();
-}
-
-int pcibios_enable_resources(struct pci_dev *dev, int mask)
-{
-    u16 cmd, old_cmd;
-    int idx;
-    struct resource *r;
-
-    pci_read_config_word(dev, PCI_COMMAND, &cmd);
-    old_cmd = cmd;
-    for(idx=0; idx<6; idx++) {
-        /* Only set up the requested stuff */
-        if (!(mask & (1<<idx)))
-            continue;
-                       
-        r = &dev->resource[idx];
-        if (!r->start && r->end) {
-            printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", dev->slot_name);
-            return -EINVAL;
-        }
-        if (r->flags & IORESOURCE_IO)
-            cmd |= PCI_COMMAND_IO;
-        if (r->flags & IORESOURCE_MEM)
-            cmd |= PCI_COMMAND_MEMORY;
-    }
-    if (dev->resource[PCI_ROM_RESOURCE].start)
-        cmd |= PCI_COMMAND_MEMORY;
-    if (cmd != old_cmd) {
-        printk("PCI: Enabling device %s (%04x -> %04x)\n", dev->slot_name, old_cmd, cmd);
-        pci_write_config_word(dev, PCI_COMMAND, cmd);
-    }
-    return 0;
-}
-
-/*
- *  If we set up a device for bus mastering, we need to check the latency
- *  timer as certain crappy BIOSes forget to set it properly.
- */
-unsigned int pcibios_max_latency = 255;
-
-void pcibios_set_master(struct pci_dev *dev)
-{
-    u8 lat;
-    pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
-    if (lat < 16)
-        lat = (64 <= pcibios_max_latency) ? 64 : pcibios_max_latency;
-    else if (lat > pcibios_max_latency)
-        lat = pcibios_max_latency;
-    else
-        return;
-    printk(KERN_DEBUG "PCI: Setting latency timer of device %s to %d\n", dev->slot_name, lat);
-    pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat);
-}
-
-int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
-                       enum pci_mmap_state mmap_state, int write_combine)
-{
-    unsigned long prot;
-
-    /* I/O space cannot be accessed via normal processor loads and
-     * stores on this platform.
-     */
-    if (mmap_state == pci_mmap_io)
-        return -EINVAL;
-
-    /* Leave vm_pgoff as-is, the PCI space address is the physical
-     * address on this platform.
-     */
-    vma->vm_flags |= (VM_SHM | VM_LOCKED | VM_IO);
-
-    prot = pgprot_val(vma->vm_page_prot);
-    if (boot_cpu_data.x86 > 3)
-        prot |= _PAGE_PCD | _PAGE_PWT;
-    vma->vm_page_prot = __pgprot(prot);
-
-    /* Write-combine setting is ignored, it is changed via the mtrr
-     * interfaces on this platform.
-     */
-    if (remap_page_range(vma->vm_start, vma->vm_pgoff << PAGE_SHIFT,
-                         vma->vm_end - vma->vm_start,
-                         vma->vm_page_prot))
-        return -EAGAIN;
-
-    return 0;
-}
diff --git a/xenolinux-2.4.25-sparse/arch/xen/kernel/pci-i386.h b/xenolinux-2.4.25-sparse/arch/xen/kernel/pci-i386.h
deleted file mode 100644 (file)
index fe70b10..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- *     Low-Level PCI Access for i386 machines.
- *
- *     (c) 1999 Martin Mares <mj@ucw.cz>
- */
-
-#undef DEBUG
-
-#ifdef DEBUG
-#define DBG(x...) printk(x)
-#else
-#define DBG(x...)
-#endif
-
-#define PCI_PROBE_BIOS         0x0001
-#define PCI_PROBE_CONF1                0x0002
-#define PCI_PROBE_CONF2                0x0004
-#define PCI_NO_SORT            0x0100
-#define PCI_BIOS_SORT          0x0200
-#define PCI_NO_CHECKS          0x0400
-#define PCI_ASSIGN_ROMS                0x1000
-#define PCI_BIOS_IRQ_SCAN      0x2000
-#define PCI_ASSIGN_ALL_BUSSES  0x4000
-
-extern unsigned int pci_probe;
-
-/* pci-i386.c */
-
-extern unsigned int pcibios_max_latency;
-extern u8 pci_cache_line_size;
-
-void pcibios_resource_survey(void);
-void pcibios_set_cacheline_size(void);
-int pcibios_enable_resources(struct pci_dev *, int);
-
-/* pci-pc.c */
-
-extern int pcibios_last_bus;
-extern struct pci_bus *pci_root_bus;
-extern struct pci_ops *pci_root_ops;
-
-/* pci-irq.c */
-
-struct irq_info {
-       u8 bus, devfn;                  /* Bus, device and function */
-       struct {
-               u8 link;                /* IRQ line ID, chipset dependent, 0=not routed */
-               u16 bitmap;             /* Available IRQs */
-       } __attribute__((packed)) irq[4];
-       u8 slot;                        /* Slot number, 0=onboard */
-       u8 rfu;
-} __attribute__((packed));
-
-struct irq_routing_table {
-       u32 signature;                  /* PIRQ_SIGNATURE should be here */
-       u16 version;                    /* PIRQ_VERSION */
-       u16 size;                       /* Table size in bytes */
-       u8 rtr_bus, rtr_devfn;          /* Where the interrupt router lies */
-       u16 exclusive_irqs;             /* IRQs devoted exclusively to PCI usage */
-       u16 rtr_vendor, rtr_device;     /* Vendor and device ID of interrupt router */
-       u32 miniport_data;              /* Crap */
-       u8 rfu[11];
-       u8 checksum;                    /* Modulo 256 checksum must give zero */
-       struct irq_info slots[0];
-} __attribute__((packed));
-
-extern unsigned int pcibios_irq_mask;
-
-void pcibios_irq_init(void);
-void pcibios_fixup_irqs(void);
-void pcibios_enable_irq(struct pci_dev *dev);
diff --git a/xenolinux-2.4.25-sparse/arch/xen/kernel/pci-irq.c b/xenolinux-2.4.25-sparse/arch/xen/kernel/pci-irq.c
deleted file mode 100644 (file)
index f530244..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-/* -*-  Mode:C; c-basic-offset:4; tab-width:4 -*-
- ****************************************************************************
- * (C) 2004 - Rolf Neugebauer - Intel Research Cambridge
- ****************************************************************************
- *
- *        File: phys_dev.c
- *      Author: Rolf Neugebauer (rolf.neugebauer@intel.com)
- *        Date: Mar 2004
- *
- * Description: XenoLinux wrappers for PCI interrupt handling.
- *              very simple since someone else is doing all the hard bits
- */
-
-
-/*
- *     Low-Level PCI Support for PC -- Routing of Interrupts
- *
- *     (c) 1999--2000 Martin Mares <mj@ucw.cz>
- */
-
-#include <linux/config.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-
-#include "pci-i386.h"
-
-#include <asm/hypervisor-ifs/physdev.h>
-
-unsigned int pcibios_irq_mask = 0xfff8;
-
-void eisa_set_level_irq(unsigned int irq)
-{
-    /* dummy */
-}
-
-void __init pcibios_irq_init(void)
-{
-       printk("PCI: IRQ init\n");
-}
-
-void __init pcibios_fixup_irqs(void)
-{
-       struct pci_dev *dev;
-    physdev_op_t op;
-       int ret;
-
-
-       printk("PCI: IRQ fixup\n");
-       pci_for_each_dev(dev) {
-
-        op.cmd  = PHYSDEVOP_FIND_IRQ;
-        op.u.find_irq.seg  = 0;
-        op.u.find_irq.bus  = dev->bus->number;
-        op.u.find_irq.dev  = PCI_SLOT(dev->devfn);
-        op.u.find_irq.func = PCI_FUNC(dev->devfn);
-
-        if ( (ret = HYPERVISOR_physdev_op(&op)) != 0 )
-        {
-            printk(KERN_ALERT "pci find irq error\n");
-            return;
-        }
-
-        dev->irq = op.u.find_irq.irq;
-        printk(KERN_INFO "PCI IRQ: [%02x:%02x:%02x] -> %d\n",
-               dev->bus->number, PCI_SLOT(dev->devfn),
-               PCI_FUNC(dev->devfn), dev->irq);
-    }
-    return;
-}
-
-void pcibios_penalize_isa_irq(int irq)
-{
-    /* dummy */
-}
-
-void pcibios_enable_irq(struct pci_dev *dev)
-{
-       u8 pin;
-       
-       pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
-
-       if (pin  && !dev->irq) {
-               printk(KERN_WARNING "PCI: No IRQ known for interrupt pin %c of "
-               "device %s.\n", 'A' + pin - 1, dev->slot_name);
-       }
-}
index afe6e4d4948899e80124d1e01764b70debc03519..48dcecd6ec3d74daafcf7836eb3e37771176182f 100644 (file)
@@ -3,7 +3,8 @@
  *
  *     (c) 1999--2000 Martin Mares <mj@ucw.cz>
  *
- * adjusted to use Xen's interface by Rolf Neugebauer
+ * Adjusted to use Xen's interface by Rolf Neugebauer, Intel Research Cambridge
+ * Further modifications by Keir Fraser, University of Cambridge
  */
 
 #include <linux/config.h>
 
 #include "pci-i386.h"
 
-int pcibios_last_bus = -1;
-struct pci_bus *pci_root_bus = NULL;
-struct pci_ops *pci_root_ops = NULL;
-
-int (*pci_config_read)(int seg, int bus, int dev, int fn, int reg, int len, u32 *value) = NULL;
-int (*pci_config_write)(int seg, int bus, int dev, int fn, int reg, int len, u32 value) = NULL;
-
-static int pci_using_acpi_prt = 0;
-
 /*
- * This interrupt-safe spinlock protects all accesses to PCI
- * configuration space.
+ * NB. The following interface functions are not included here:
+ *  1. void eisa_set_level_irq(unsigned int irq)
+ *  2. irq_routing_table * __devinit pcibios_get_irq_routing_table(void)
+ *  3. int pcibios_set_irq_routing(struct pci_dev *dev, int pin, int irq)
+ * All are used by the ACPI driver. This should be ported to Xen if it is
+ * ever required -- Xen is the ultimate source for IRQ-routing knowledge.
  */
-static spinlock_t pci_config_lock = SPIN_LOCK_UNLOCKED;
+
+struct pci_ops *pci_root_ops = NULL;
+
+int (*pci_config_read)(int seg, int bus, int dev, int fn, 
+                       int reg, int len, u32 *value) = NULL;
+int (*pci_config_write)(int seg, int bus, int dev, int fn,
+                        int reg, int len, u32 value) = NULL;
 
 unsigned int pci_probe = PCI_PROBE_BIOS;
 
-/*
- * Functions for accessing PCI configuration space with type 1 accesses
- */
+struct pci_fixup pcibios_fixups[] = { { 0 } };
 
-static int pci_confx_read (int seg, int bus, int dev, int fn, int reg, 
-                           int len, u32 *value)
+static int pci_confx_read(int seg, int bus, int dev, int fn, int reg, 
+                          int len, u32 *value)
 {
     int ret;
     physdev_op_t op;
@@ -52,27 +52,23 @@ static int pci_confx_read (int seg, int bus, int dev, int fn, int reg,
     if (bus > 255 || dev > 31 || fn > 7 || reg > 255)
         return -EINVAL;
 
-    op.cmd = PHYSDEVOP_CFGREG_READ;
-    op.u.cfg_read.seg  = seg;
-    op.u.cfg_read.bus  = bus;
-    op.u.cfg_read.dev  = dev;
-    op.u.cfg_read.func = fn;
-    op.u.cfg_read.reg  = reg;
-    op.u.cfg_read.len  = len;
+    op.cmd = PHYSDEVOP_PCI_CFGREG_READ;
+    op.u.pci_cfgreg_read.bus  = bus;
+    op.u.pci_cfgreg_read.dev  = dev;
+    op.u.pci_cfgreg_read.func = fn;
+    op.u.pci_cfgreg_read.reg  = reg;
+    op.u.pci_cfgreg_read.len  = len;
 
     if ( (ret = HYPERVISOR_physdev_op(&op)) != 0 )
-    {
-        //printk(KERN_ALERT "pci config read error\n");
         return ret;
-    }
 
-    *value = op.u.cfg_read.value;
+    *value = op.u.pci_cfgreg_read.value;
 
     return 0;
 }
 
-static int pci_confx_write (int seg, int bus, int dev, int fn, int reg, 
-                            int len, u32 value)
+static int pci_confx_write(int seg, int bus, int dev, int fn, int reg, 
+                           int len, u32 value)
 {
     int ret;
     physdev_op_t op;
@@ -80,25 +76,22 @@ static int pci_confx_write (int seg, int bus, int dev, int fn, int reg,
     if ((bus > 255 || dev > 31 || fn > 7 || reg > 255)) 
         return -EINVAL;
 
-    op.cmd = PHYSDEVOP_CFGREG_WRITE;
-    op.u.cfg_write.seg   = seg;
-    op.u.cfg_write.bus   = bus;
-    op.u.cfg_write.dev   = dev;
-    op.u.cfg_write.func  = fn;
-    op.u.cfg_write.reg   = reg;
-    op.u.cfg_write.len   = len;
-    op.u.cfg_write.value = value;
+    op.cmd = PHYSDEVOP_PCI_CFGREG_WRITE;
+    op.u.pci_cfgreg_write.bus   = bus;
+    op.u.pci_cfgreg_write.dev   = dev;
+    op.u.pci_cfgreg_write.func  = fn;
+    op.u.pci_cfgreg_write.reg   = reg;
+    op.u.pci_cfgreg_write.len   = len;
+    op.u.pci_cfgreg_write.value = value;
 
     if ( (ret = HYPERVISOR_physdev_op(&op)) != 0 )
-    {
-        //printk(KERN_ALERT "pci config write error\n");
         return ret;
-    }
     return 0;
 }
 
 
-static int pci_confx_read_config_byte(struct pci_dev *dev, int where, u8 *value)
+static int pci_confx_read_config_byte(struct pci_dev *dev, 
+                                      int where, u8 *value)
 {
     int result; 
     u32 data;
@@ -111,7 +104,8 @@ static int pci_confx_read_config_byte(struct pci_dev *dev, int where, u8 *value)
     return result;
 }
 
-static int pci_confx_read_config_word(struct pci_dev *dev, int where, u16 *value)
+static int pci_confx_read_config_word(struct pci_dev *dev, 
+                                      int where, u16 *value)
 {
     int result; 
     u32 data;
@@ -124,31 +118,35 @@ static int pci_confx_read_config_word(struct pci_dev *dev, int where, u16 *value
     return result;
 }
 
-static int pci_confx_read_config_dword(struct pci_dev *dev, int where, u32 *value)
+static int pci_confx_read_config_dword(struct pci_dev *dev, 
+                                       int where, u32 *value)
 {
     return pci_confx_read(0, dev->bus->number, PCI_SLOT(dev->devfn), 
                           PCI_FUNC(dev->devfn), where, 4, value);
 }
 
-static int pci_confx_write_config_byte(struct pci_dev *dev, int where, u8 value)
+static int pci_confx_write_config_byte(struct pci_dev *dev, 
+                                       int where, u8 value)
 {
     return pci_confx_write(0, dev->bus->number, PCI_SLOT(dev->devfn), 
                            PCI_FUNC(dev->devfn), where, 1, value);
 }
 
-static int pci_confx_write_config_word(struct pci_dev *dev, int where, u16 value)
+static int pci_confx_write_config_word(struct pci_dev *dev, 
+                                       int where, u16 value)
 {
     return pci_confx_write(0, dev->bus->number, PCI_SLOT(dev->devfn), 
                            PCI_FUNC(dev->devfn), where, 2, value);
 }
 
-static int pci_confx_write_config_dword(struct pci_dev *dev, int where, u32 value)
+static int pci_confx_write_config_dword(struct pci_dev *dev, 
+                                        int where, u32 value)
 {
     return pci_confx_write(0, dev->bus->number, PCI_SLOT(dev->devfn), 
                            PCI_FUNC(dev->devfn), where, 4, value);
 }
 
-static struct pci_ops pci_direct_confx = {
+static struct pci_ops pci_conf_xen = {
     pci_confx_read_config_byte,
     pci_confx_read_config_word,
     pci_confx_read_config_dword,
@@ -157,129 +155,14 @@ static struct pci_ops pci_direct_confx = {
     pci_confx_write_config_dword
 };
 
-
-
-static struct pci_ops * __devinit pci_check_xen(void)
-{
-    unsigned long flags;
-
-    __save_flags(flags); __cli();
-
-    printk(KERN_INFO "PCI: Using Xen interface\n");
-
-    __restore_flags(flags);
-
-    return &pci_direct_confx;
-}
-
-struct pci_fixup pcibios_fixups[] = { {0}};
-
-
-struct irq_routing_table * __devinit pcibios_get_irq_routing_table(void)
-{
-    return NULL;
-}
-
-int pcibios_set_irq_routing(struct pci_dev *dev, int pin, int irq)
-{
-    return 0;
+void pcibios_penalize_isa_irq(int irq)
+{ 
+    /* nothing */
 }
 
-/*
- * Several buggy motherboards address only 16 devices and mirror
- * them to next 16 IDs. We try to detect this `feature' on all
- * primary buses (those containing host bridges as they are
- * expected to be unique) and remove the ghost devices.
- */
-
-static void __devinit pcibios_fixup_ghosts(struct pci_bus *b)
+void __devinit pcibios_fixup_bus(struct pci_bus *b)
 {
-    struct list_head *ln, *mn;
-    struct pci_dev *d, *e;
-    int mirror = PCI_DEVFN(16,0);
-    int seen_host_bridge = 0;
-    int i;
-
-    DBG("PCI: Scanning for ghost devices on bus %d\n", b->number);
-    for (ln=b->devices.next; ln != &b->devices; ln=ln->next) {
-        d = pci_dev_b(ln);
-        if ((d->class >> 8) == PCI_CLASS_BRIDGE_HOST)
-            seen_host_bridge++;
-        for (mn=ln->next; mn != &b->devices; mn=mn->next) {
-            e = pci_dev_b(mn);
-            if (e->devfn != d->devfn + mirror ||
-                e->vendor != d->vendor ||
-                e->device != d->device ||
-                e->class != d->class)
-                continue;
-            for(i=0; i<PCI_NUM_RESOURCES; i++)
-                if (e->resource[i].start != d->resource[i].start ||
-                    e->resource[i].end != d->resource[i].end ||
-                    e->resource[i].flags != d->resource[i].flags)
-                    continue;
-            break;
-        }
-        if (mn == &b->devices)
-            return;
-    }
-    if (!seen_host_bridge)
-        return;
-    printk(KERN_WARNING "PCI: Ignoring ghost devices on bus %02x\n", b->number);
-
-    ln = &b->devices;
-    while (ln->next != &b->devices) {
-        d = pci_dev_b(ln->next);
-        if (d->devfn >= mirror) {
-            list_del(&d->global_list);
-            list_del(&d->bus_list);
-            kfree(d);
-        } else
-            ln = ln->next;
-    }
-}
-
-/*
- * Discover remaining PCI buses in case there are peer host bridges.
- * We use the number of last PCI bus provided by the PCI BIOS.
- */
-static void __devinit pcibios_fixup_peer_bridges(void)
-{
-    int n;
-    struct pci_bus bus;
-    struct pci_dev dev;
-    u16 l;
-    
-    if (pcibios_last_bus <= 0 || pcibios_last_bus >= 0xff)
-        return;
-    DBG("PCI: Peer bridge fixup\n");
-    for (n=0; n <= pcibios_last_bus; n++) {
-        if (pci_bus_exists(&pci_root_buses, n))
-            continue;
-        bus.number = n;
-        bus.ops = pci_root_ops;
-        dev.bus = &bus;
-        for(dev.devfn=0; dev.devfn<256; dev.devfn += 8)
-            if (!pci_read_config_word(&dev, PCI_VENDOR_ID, &l) &&
-                l != 0x0000 && l != 0xffff) {
-                DBG("Found device at %02x:%02x [%04x]\n", n, dev.devfn, l);
-                printk(KERN_INFO "PCI: Discovered peer bus %02x\n", n);
-                pci_scan_bus(n, pci_root_ops, NULL);
-                break;
-            }
-    }
-}
-
-
-/*
- *  Called after each bus is probed, but before its children
- *  are examined.
- */
-
-void __devinit  pcibios_fixup_bus(struct pci_bus *b)
-{
-    pcibios_fixup_ghosts(b);
     pci_read_bridge_bases(b);
-    return;
 }
 
 struct pci_bus * __devinit pcibios_scan_root(int busnum)
@@ -287,78 +170,91 @@ struct pci_bus * __devinit pcibios_scan_root(int busnum)
     struct list_head *list;
     struct pci_bus *bus;
 
-    list_for_each(list, &pci_root_buses) {
+    list_for_each ( list, &pci_root_buses )
+    {
         bus = pci_bus_b(list);
-        if (bus->number == busnum) {
-            /* Already scanned */
+        if ( bus->number == busnum )
             return bus;
-        }
     }
 
     printk("PCI: Probing PCI hardware (bus %02x)\n", busnum);
-
     return pci_scan_bus(busnum, pci_root_ops, NULL);
 }
 
-void __devinit pcibios_config_init(void)
+void __init pcibios_init(void)
 {
-    /*
-     * Try all known PCI access methods. Note that we support using 
-     * both PCI BIOS and direct access, with a preference for direct.
-     */
+    int bus;
+    physdev_op_t op;
+
+    if ( !pci_probe )
+        return;
 
-    pci_root_ops = pci_check_xen();
-    pci_config_read = pci_confx_read;
+    pci_root_ops     = &pci_conf_xen;
+    pci_config_read  = pci_confx_read;
     pci_config_write = pci_confx_write;
 
-    return;
-}
+    pcibios_set_cacheline_size();
 
-void __init pcibios_init(void)
-{
-    if (!pci_root_ops)
-        pcibios_config_init();
-    if (!pci_root_ops) {
+    op.cmd = PHYSDEVOP_PCI_PROBE_ROOT_BUSES;
+    if ( HYPERVISOR_physdev_op(&op) != 0 )
+    {
         printk(KERN_WARNING "PCI: System does not support PCI\n");
         return;
     }
 
-    pcibios_set_cacheline_size();
-
     printk(KERN_INFO "PCI: Probing PCI hardware\n");
-
-    if (!pci_using_acpi_prt) {
-        pci_root_bus = pcibios_scan_root(0);
-        pcibios_irq_init();
-        pcibios_fixup_peer_bridges();
-        pcibios_fixup_irqs();
-    }
+    for ( bus = 0; bus < 256; bus++ )
+        if ( test_bit(bus, &op.u.pci_probe_root_buses.busmask[0]) )
+            (void)pcibios_scan_root(bus);
 
     pcibios_resource_survey();
 }
 
-char * __devinit  pcibios_setup(char *str)
+char * __devinit pcibios_setup(char *str)
 {
-    if (!strcmp(str, "off")) {
+    if ( !strcmp(str, "off") )
         pci_probe = 0;
-        return NULL;
-    }
     return NULL;
 }
 
 unsigned int pcibios_assign_all_busses(void)
 {
-    return (pci_probe & PCI_ASSIGN_ALL_BUSSES) ? 1 : 0;
+    return 0;
 }
 
 int pcibios_enable_device(struct pci_dev *dev, int mask)
 {
     int err;
+    u8  pin;
+    physdev_op_t op;
 
-    if ((err = pcibios_enable_resources(dev, mask)) < 0)
+    /* Inform Xen that we are going to use this device. */
+    op.cmd = PHYSDEVOP_PCI_INITIALISE_DEVICE;
+    op.u.pci_initialise_device.bus  = dev->bus->number;
+    op.u.pci_initialise_device.dev  = PCI_SLOT(dev->devfn);
+    op.u.pci_initialise_device.func = PCI_FUNC(dev->devfn);
+    if ( (err = HYPERVISOR_physdev_op(&op)) != 0 )
         return err;
 
-    pcibios_enable_irq(dev);
+    /* Now we can bind to the very final IRQ line. */
+    pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &pin);
+    dev->irq = pin;
+
+    /* Turn on device I/O and memory access as necessary. */
+    if ( (err = pcibios_enable_resources(dev, mask)) < 0 )
+        return err;
+
+    /* Sanity-check that an interrupt-producing device is routed to an IRQ. */
+    pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
+    if ( pin != 0 )
+    {
+        if ( dev->irq != 0 )
+            printk(KERN_INFO "PCI: Obtained IRQ %d for device %s\n",
+                   dev->irq, dev->slot_name);
+        else
+            printk(KERN_WARNING "PCI: No IRQ known for interrupt pin %c of "
+                   "device %s.\n", 'A' + pin - 1, dev->slot_name);
+    }
 
     return 0;
 }
index b6679d05df04bd590ed6b5656ae16fc44b29958b..faaf923c301d79d3e54087555ce09d0744bbcb7f 100755 (executable)
@@ -200,6 +200,9 @@ ln -sf ../asm-i386/user.h
 cd ../../arch/xen/kernel
 ln -sf ../../i386/kernel/i387.c
 ln -sf ../../i386/kernel/init_task.c
+ln -sf ../../i386/kernel/pci-dma.c
+ln -sf ../../i386/kernel/pci-i386.c
+ln -sf ../../i386/kernel/pci-i386.h
 ln -sf ../../i386/kernel/ptrace.c
 ln -sf ../../i386/kernel/semaphore.c 
 ln -sf ../../i386/kernel/sys_i386.c